{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "bda5a4a6-adf0-43e2-9f4b-5c3f4c98a2a5",
   "metadata": {},
   "source": [
    "### 正则表达式详细讲解\n",
    "\n",
    "**正则表达式**（Regular Expression，简称 **RegEx**）是一种用于匹配字符串的强大工具。它允许我们通过定义一个特定的模式来查找、替换、提取或验证文本数据。在数据处理、爬虫、文本解析等领域，正则表达式是不可或缺的。\n",
    "\n",
    "正则表达式由普通字符（如字母、数字）和特殊符号组成，用于定义要匹配的字符序列。下面是正则表达式的详细讲解，帮助学生更好地理解和掌握其使用。\n",
    "\n",
    "---\n",
    "\n",
    "### **1. 基本概念**\n",
    "\n",
    "- **字符**：在正则表达式中，每一个字符本身都有特殊含义。例如，`a` 匹配字符串中的字符 \"a\"。\n",
    "- **元字符**：正则表达式的特殊符号，具有特殊的含义，如 `.`，`*`，`+`，`[]` 等。\n",
    "\n",
    "### **2. 元字符和其作用**\n",
    "\n",
    "#### **`.` （点）**\n",
    "`.` 匹配除换行符外的任意一个字符。\n",
    "\n",
    "**例子：**\n",
    "- 正则表达式：`h.t`\n",
    "- 匹配：`hat`，`hot`，`hit` 等\n",
    "\n",
    "#### **`*` （星号）**\n",
    "`*` 表示匹配前面的字符 0 次或更多次。\n",
    "\n",
    "**例子：**\n",
    "- 正则表达式：`ca*t`\n",
    "- 匹配：`ct`，`cat`，`caaat` 等\n",
    "\n",
    "#### **`+` （加号）**\n",
    "`+` 表示匹配前面的字符 1 次或更多次。\n",
    "\n",
    "**例子：**\n",
    "- 正则表达式：`ca+t`\n",
    "- 匹配：`cat`，`caat`，但不匹配 `ct`\n",
    "\n",
    "#### **`?` （问号）**\n",
    "`?` 表示匹配前面的字符 0 次或 1 次。\n",
    "\n",
    "**例子：**\n",
    "- 正则表达式：`ca?t`\n",
    "- 匹配：`ct` 或 `cat`\n",
    "\n",
    "#### **`[]` （方括号）**\n",
    "`[]` 表示字符集，匹配方括号内的任意一个字符。\n",
    "\n",
    "**例子：**\n",
    "- 正则表达式：`[ch]at`\n",
    "- 匹配：`cat` 或 `hat`\n",
    "\n",
    "#### **`^` 和 `$`**\n",
    "- `^` 用于匹配字符串的开头。\n",
    "- `$` 用于匹配字符串的结尾。\n",
    "\n",
    "**例子：**\n",
    "- 正则表达式：`^abc` 匹配以 `abc` 开头的字符串。\n",
    "- 正则表达式：`xyz$` 匹配以 `xyz` 结尾的字符串。\n",
    "\n",
    "#### **`|` （管道符）**\n",
    "`|` 表示 \"或\" 的关系，匹配左边或右边的任意表达式。\n",
    "\n",
    "**例子：**\n",
    "- 正则表达式：`a|b`\n",
    "- 匹配：`a` 或 `b`\n",
    "\n",
    "---\n",
    "\n",
    "### **3. 转义字符**\n",
    "\n",
    "有时我们需要匹配正则表达式中的元字符本身（如 `.`、`*`、`+` 等），这时就需要使用 **转义字符** `\\`。\n",
    "\n",
    "**例子：**\n",
    "- 正则表达式：`\\.` 匹配实际的点字符 `.`，而不是任意字符。\n",
    "\n",
    "---\n",
    "\n",
    "### **4. 捕获组 `()`**\n",
    "\n",
    "捕获组通过 `()` 将匹配的部分括起来，以便后续处理或使用。它也可以用于重复匹配特定的模式。\n",
    "\n",
    "**例子：**\n",
    "- 正则表达式：`(ab)+`\n",
    "- 匹配：`ab`，`abab`，`ababab` 等\n",
    "\n",
    "**捕获组提取例子：**\n",
    "\n",
    "```python\n",
    "import re\n",
    "\n",
    "text = \"John's phone number is 123-456-7890.\"\n",
    "pattern = r\"(\\d{3})-(\\d{3})-(\\d{4})\"\n",
    "match = re.search(pattern, text)\n",
    "if match:\n",
    "    print(f\"区号: {match.group(1)}, 中间号码: {match.group(2)}, 末尾号码: {match.group(3)}\")\n",
    "```\n",
    "\n",
    "**输出：**\n",
    "```\n",
    "区号: 123, 中间号码: 456, 末尾号码: 7890\n",
    "```\n",
    "\n",
    "---\n",
    "\n",
    "### **5. 特殊字符 `\\d`，`\\w`，`\\s` 等**\n",
    "\n",
    "- `\\d`：匹配任意数字，等价于 `[0-9]`。\n",
    "- `\\w`：匹配任意字母、数字或下划线字符，等价于 `[A-Za-z0-9_]`。\n",
    "- `\\s`：匹配任意空白字符（包括空格、制表符等）。\n",
    "\n",
    "**例子：**\n",
    "- 正则表达式：`\\d{3}` 匹配任意三个数字。\n",
    "\n",
    "---\n",
    "\n",
    "### **6. 贪婪与非贪婪匹配**\n",
    "\n",
    "正则表达式中的元字符 `*` 和 `+` 默认是 **贪婪匹配**，即它们会尽可能多地匹配字符。为了实现 **非贪婪匹配**，可以在元字符后面加 `?`。\n",
    "\n",
    "**例子：**\n",
    "- 正则表达式：`<.*>` 会贪婪地匹配 `<div>hello</div>text` 中的所有内容，包括整个 `<div>hello</div>`。\n",
    "- 正则表达式：`<.*?>` 则是非贪婪匹配，它只会匹配 `<div>`。\n",
    "\n",
    "---\n",
    "\n",
    "### **7. 正则表达式在 Python 中的使用**\n",
    "\n",
    "Python 提供了 `re` 模块来使用正则表达式。常用函数如下：\n",
    "\n",
    "- `re.search()`：在整个字符串中搜索正则表达式的匹配项。\n",
    "- `re.findall()`：返回所有非重叠的匹配项。\n",
    "- `re.sub()`：替换字符串中匹配的部分。\n",
    "- `re.split()`：根据正则表达式匹配项拆分字符串。\n",
    "\n",
    "**例子：**\n",
    "\n",
    "```python\n",
    "import re\n",
    "\n",
    "# 示例文本\n",
    "text = \"My email is student@example.com, and my phone number is 123-456-7890.\"\n",
    "\n",
    "# 匹配 email\n",
    "email_pattern = r\"\\w+@\\w+\\.\\w+\"\n",
    "email = re.search(email_pattern, text)\n",
    "print(\"匹配的 Email:\", email.group())\n",
    "\n",
    "# 替换电话号码\n",
    "phone_pattern = r\"\\d{3}-\\d{3}-\\d{4}\"\n",
    "masked_text = re.sub(phone_pattern, \"XXX-XXX-XXXX\", text)\n",
    "print(\"替换后的文本:\", masked_text)\n",
    "```\n",
    "\n",
    "---\n",
    "\n",
    "### **8. 正则表达式的应用场景**\n",
    "\n",
    "1. **爬虫数据解析**：从 HTML 数据中提取关键信息，如标题、链接、价格等。\n",
    "2. **数据清洗**：用于识别和清理特定格式的数据，如删除特殊字符、替换格式等。\n",
    "3. **日志分析**：从系统日志中提取时间戳、错误消息等有用信息。\n",
    "4. **文本搜索**：查找文本中的特定模式，如电子邮件地址、电话号码等。\n",
    "\n",
    "---\n",
    "\n",
    "### 总结：\n",
    "\n",
    "正则表达式是一种非常强大且灵活的工具，广泛应用于文本处理和数据解析领域。通过以上讲解，学生可以掌握正则表达式的基本概念、常用的匹配规则，以及如何在 Python 中实际使用正则表达式进行数据处理。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "29021493-85eb-4fdc-aad1-9d7f0e35d747",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "区号: 010, 中间号码: 8809, 末尾号码: 5926\n"
     ]
    }
   ],
   "source": [
    "import re\n",
    "\n",
    "text = \"John's phone number is 010-8809-5926.\"\n",
    "pattern = r\"(\\d{3})-(\\d{4})-(\\d{4})\"\n",
    "match = re.search(pattern, text)\n",
    "if match:\n",
    "    print(f\"区号: {match.group(1)}, 中间号码: {match.group(2)}, 末尾号码: {match.group(3)}\")\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "4a43f82c-a933-42f9-ab58-1996fc835daf",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "匹配的 Email: student@example.com\n",
      "替换后的文本: My email is student@example.com, and my phone number is XXX-XXX-XXXX.\n"
     ]
    }
   ],
   "source": [
    "import re\n",
    "\n",
    "# 示例文本\n",
    "text = \"My email is student@example.com, and my phone number is 123-456-7890.\"\n",
    "\n",
    "# 匹配 email\n",
    "email_pattern = r\"\\w+@\\w+\\.\\w+\"\n",
    "email = re.search(email_pattern, text)\n",
    "print(\"匹配的 Email:\", email.group())\n",
    "\n",
    "# 替换电话号码\n",
    "phone_pattern = r\"\\d{3}-\\d{3}-\\d{4}\"\n",
    "masked_text = re.sub(phone_pattern, \"XXX-XXX-XXXX\", text)\n",
    "print(\"替换后的文本:\", masked_text)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "874e0aac-d404-4f6b-9a09-be3bebd68403",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "电影: 肖申克的救赎\n",
      "评分: 9.7\n",
      "导演: 弗兰克·德拉邦特 Frank Darabont&nbsp;&nbsp;&nbsp;主演: 蒂姆·罗宾斯 Tim Robbins /...\n",
      "简评: 希望让人自由。\n",
      "----------------------------------------\n",
      "电影: &nbsp;/&nbsp;The Shawshank Redemption\n",
      "评分: 9.6\n",
      "导演: 陈凯歌 Kaige Chen&nbsp;&nbsp;&nbsp;主演: 张国荣 Leslie Cheung / 张丰毅 Fengyi Zha...\n",
      "简评: 风华绝代。\n",
      "----------------------------------------\n",
      "电影: 霸王别姬\n",
      "评分: 9.5\n",
      "导演: 罗伯特·泽米吉斯 Robert Zemeckis&nbsp;&nbsp;&nbsp;主演: 汤姆·汉克斯 Tom Hanks / ...\n",
      "简评: 一部美国近现代史。\n",
      "----------------------------------------\n",
      "电影: 阿甘正传\n",
      "评分: 9.5\n",
      "导演: 詹姆斯·卡梅隆 James Cameron&nbsp;&nbsp;&nbsp;主演: 莱昂纳多·迪卡普里奥 Leonardo...\n",
      "简评: 失去的才是永恒的。 \n",
      "----------------------------------------\n",
      "电影: &nbsp;/&nbsp;Forrest Gump\n",
      "评分: 9.4\n",
      "导演: 宫崎骏 Hayao Miyazaki&nbsp;&nbsp;&nbsp;主演: 柊瑠美 Rumi Hîragi / 入野自由 Miy...\n",
      "简评: 最好的宫崎骏，最好的久石让。 \n",
      "----------------------------------------\n",
      "电影: 泰坦尼克号\n",
      "评分: 9.4\n",
      "导演: 吕克·贝松 Luc Besson&nbsp;&nbsp;&nbsp;主演: 让·雷诺 Jean Reno / 娜塔莉·波特曼 ...\n",
      "简评: 怪蜀黍和小萝莉不得不说的故事。\n",
      "----------------------------------------\n",
      "电影: &nbsp;/&nbsp;Titanic\n",
      "评分: 9.5\n",
      "导演: 罗伯托·贝尼尼 Roberto Benigni&nbsp;&nbsp;&nbsp;主演: 罗伯托·贝尼尼 Roberto Beni...\n",
      "简评: 最美的谎言。\n",
      "----------------------------------------\n",
      "电影: 千与千寻\n",
      "评分: 9.4\n",
      "导演: 克里斯托弗·诺兰 Christopher Nolan&nbsp;&nbsp;&nbsp;主演: 马修·麦康纳 Matthew Mc...\n",
      "简评: 爱是一种力量，让我们超越时空感知它的存在。\n",
      "----------------------------------------\n",
      "电影: &nbsp;/&nbsp;千と千尋の神隠し\n",
      "评分: 9.4\n",
      "导演: 克里斯托弗·诺兰 Christopher Nolan&nbsp;&nbsp;&nbsp;主演: 莱昂纳多·迪卡普里奥 Le...\n",
      "简评: 诺兰给了我们一场无法盗取的梦。\n",
      "----------------------------------------\n",
      "电影: 这个杀手不太冷\n",
      "评分: 9.4\n",
      "导演: 彼得·威尔 Peter Weir&nbsp;&nbsp;&nbsp;主演: 金·凯瑞 Jim Carrey / 劳拉·琳妮 Lau...\n",
      "简评: 如果再也不能见到你，祝你早安，午安，晚安。\n",
      "----------------------------------------\n",
      "电影: &nbsp;/&nbsp;Léon\n",
      "评分: 9.5\n",
      "导演: 史蒂文·斯皮尔伯格 Steven Spielberg&nbsp;&nbsp;&nbsp;主演: 连姆·尼森 Liam Neeson...\n",
      "简评: 拯救一个人，就是拯救整个世界。\n",
      "----------------------------------------\n",
      "电影: 美丽人生\n",
      "评分: 9.4\n",
      "导演: 莱塞·霍尔斯道姆 Lasse Hallström&nbsp;&nbsp;&nbsp;主演: 理查·基尔 Richard Ger...\n",
      "简评: 永远都不能忘记你所爱的人。\n",
      "----------------------------------------\n",
      "电影: &nbsp;/&nbsp;La vita è bella\n",
      "评分: 9.3\n",
      "导演: 朱塞佩·托纳多雷 Giuseppe Tornatore&nbsp;&nbsp;&nbsp;主演: 蒂姆·罗斯 Tim Roth / ...\n",
      "简评: 每个人都要走一条自己坚定了的路，就算是粉身碎骨。 \n",
      "----------------------------------------\n",
      "电影: 星际穿越\n",
      "评分: 9.2\n",
      "导演: 拉库马·希拉尼 Rajkumar Hirani&nbsp;&nbsp;&nbsp;主演: 阿米尔·汗 Aamir Khan / 卡...\n",
      "简评: 英俊版憨豆，高情商版谢耳朵。\n",
      "----------------------------------------\n",
      "电影: &nbsp;/&nbsp;Interstellar\n",
      "评分: 9.3\n",
      "导演: 克里斯托夫·巴拉蒂 Christophe Barratier&nbsp;&nbsp;&nbsp;主演: 让-巴蒂斯特·莫尼...\n",
      "简评: 天籁一般的童声，是最接近上帝的存在。 \n",
      "----------------------------------------\n",
      "电影: 盗梦空间\n",
      "评分: 9.3\n",
      "导演: 安德鲁·斯坦顿 Andrew Stanton&nbsp;&nbsp;&nbsp;主演: 本·贝尔特 Ben Burtt / 艾丽...\n",
      "简评: 小瓦力，大人生。\n",
      "----------------------------------------\n",
      "电影: &nbsp;/&nbsp;Inception\n",
      "评分: 9.2\n",
      "导演: 拜伦·霍华德 Byron Howard / 瑞奇·摩尔 Rich Moore&nbsp;&nbsp;&nbsp;主演: 金妮弗·...\n",
      "简评: 迪士尼给我们营造的乌托邦就是这样，永远善良勇敢，永远出乎意料。\n",
      "----------------------------------------\n",
      "电影: 楚门的世界\n",
      "评分: 9.3\n",
      "导演: 刘伟强 / 麦兆辉&nbsp;&nbsp;&nbsp;主演: 刘德华 Andy Lau / 梁朝伟 Tony Leung Chiu W...\n",
      "简评: 香港电影史上永不过时的杰作。\n",
      "----------------------------------------\n",
      "电影: &nbsp;/&nbsp;The Truman Show\n",
      "评分: 9.6\n",
      "导演: 比利·怀尔德 Billy Wilder&nbsp;&nbsp;&nbsp;主演: 泰隆·鲍华 Tyrone Power / 玛琳·...\n",
      "简评: 比利·怀德满分作品。\n",
      "----------------------------------------\n",
      "电影: 辛德勒的名单\n",
      "评分: 9.2\n",
      "导演: 刘镇伟 Jeffrey Lau&nbsp;&nbsp;&nbsp;主演: 周星驰 Stephen Chow / 吴孟达 Man Tat Ng...\n",
      "简评: 一生所爱。\n",
      "----------------------------------------\n",
      "电影: &nbsp;/&nbsp;Schindler&#39;s List\n",
      "评分: 9.3\n",
      "导演: 黄东赫 Dong-hyuk Hwang&nbsp;&nbsp;&nbsp;主演: 孔侑 Yoo Gong / 郑有美 Yu-mi Jung /...\n",
      "简评: 我们一路奋战不是为了改变世界，而是为了不让世界改变我们。\n",
      "----------------------------------------\n",
      "电影: 忠犬八公的故事\n",
      "评分: 9.3\n",
      "导演: 弗朗西斯·福特·科波拉 Francis Ford Coppola&nbsp;&nbsp;&nbsp;主演: 马龙·白兰度 M...\n",
      "简评: 千万不要记恨你的对手，这样会让你失去理智。\n",
      "----------------------------------------\n",
      "电影: &nbsp;/&nbsp;Hachi: A Dog&#39;s Tale\n",
      "评分: 9.3\n",
      "导演: 奥利维·那卡什 Olivier Nakache / 艾力克·托兰达 Eric Toledano&nbsp;&nbsp;&nbsp;主...\n",
      "简评: 满满温情的高雅喜剧。\n",
      "----------------------------------------\n",
      "电影: 海上钢琴师\n",
      "评分: 9.2\n",
      "导演: 加布里尔·穆奇诺 Gabriele Muccino&nbsp;&nbsp;&nbsp;主演: 威尔·史密斯 Will Smith ...\n",
      "简评: 平民励志片。 \n",
      "----------------------------------------\n",
      "电影: &nbsp;/&nbsp;La leggenda del pianista sull&#39;oceano\n",
      "评分: 9.1\n",
      "导演: 李·昂克里奇 Lee Unkrich / 阿德里安·莫利纳 Adrian Molina&nbsp;&nbsp;&nbsp;主演: ...\n",
      "简评: 死亡不是真的逝去，遗忘才是永恒的消亡。\n",
      "----------------------------------------\n"
     ]
    }
   ],
   "source": [
    "import requests\n",
    "import re\n",
    "\n",
    "# 设置请求的 URL\n",
    "url = \"https://movie.douban.com/top250\"\n",
    "\n",
    "# 定义请求头，模拟浏览器\n",
    "headers = {\n",
    "    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36'\n",
    "}\n",
    "\n",
    "# 发送 GET 请求，获取页面内容\n",
    "response = requests.get(url, headers=headers)\n",
    "\n",
    "# 检查请求是否成功\n",
    "if response.status_code == 200:\n",
    "    html_content = response.text  # 获取网页 HTML 内容\n",
    "\n",
    "    # 正则表达式匹配电影标题\n",
    "    title_pattern = re.compile(r'<span class=\"title\">([^<]+)</span>')\n",
    "    titles = title_pattern.findall(html_content)\n",
    "\n",
    "    # 正则表达式匹配电影评分\n",
    "    rating_pattern = re.compile(r'<span class=\"rating_num\" property=\"v:average\">([\\d.]+)</span>')\n",
    "    ratings = rating_pattern.findall(html_content)\n",
    "\n",
    "    # 正则表达式匹配导演信息（从< p >标签中的 \"导演: \" 后开始）\n",
    "    director_pattern = re.compile(r'导演: ([^<]+)')\n",
    "    directors = director_pattern.findall(html_content)\n",
    "\n",
    "    # 正则表达式匹配电影的简短描述（可能存在，不一定有）\n",
    "    quote_pattern = re.compile(r'<span class=\"inq\">([^<]+)</span>')\n",
    "    quotes = quote_pattern.findall(html_content)\n",
    "\n",
    "    # 确定可迭代的最小长度，避免超出索引范围\n",
    "    min_length = min(len(titles), len(ratings), len(directors))\n",
    "\n",
    "    # 打印提取的信息\n",
    "    for i in range(min_length):\n",
    "        print(f\"电影: {titles[i]}\")\n",
    "        print(f\"评分: {ratings[i]}\")\n",
    "        print(f\"导演: {directors[i]}\")\n",
    "        if i < len(quotes):\n",
    "            print(f\"简评: {quotes[i]}\")\n",
    "        else:\n",
    "            print(\"简评: 暂无\")\n",
    "        print(\"-\" * 40)\n",
    "\n",
    "else:\n",
    "    print(f\"请求失败，状态码: {response.status_code}\")\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d862d658-d2b6-464c-a79c-41e4630580fd",
   "metadata": {},
   "source": [
    "### 解析正则表达式匹配规则\n",
    "\n",
    "在这段代码中，我们通过正则表达式从 `html_content` 中提取电影的标题、评分、导演以及简短描述。下面详细解释每个正则表达式的构造和匹配逻辑。\n",
    "\n",
    "---\n",
    "\n",
    "### **1. 匹配电影标题**\n",
    "\n",
    "```python\n",
    "title_pattern = re.compile(r'<span class=\"title\">([^<]+)</span>')\n",
    "titles = title_pattern.findall(html_content)\n",
    "```\n",
    "\n",
    "#### **解释：**\n",
    "- **正则表达式**：`<span class=\"title\">([^<]+)</span>`\n",
    "- **匹配内容**：电影标题，如 `<span class=\"title\">电影名</span>`\n",
    "  \n",
    "**具体解释：**\n",
    "- `<span class=\"title\">`：这是固定的字符串，表示我们要找到 `span` 标签，且 `class` 属性为 `title`。这个部分用于定位网页中的电影名称。\n",
    "- `([^<]+)`：这是一个捕获组，用于提取 `span` 标签中的内容。`[^<]` 表示 **匹配任意不是 `<` 的字符**，`+` 表示 **匹配 1 次或多次**。所以这个部分会提取标签内的文字内容（即电影标题）。\n",
    "- `</span>`：表示 `span` 标签的关闭部分。\n",
    "\n",
    "**工作原理**：该表达式从每个包含电影标题的 `span` 标签中提取出文字部分。捕获组 `([^<]+)` 用于抓取标题，防止其他 HTML 标签干扰。\n",
    "\n",
    "---\n",
    "\n",
    "### **2. 匹配电影评分**\n",
    "\n",
    "```python\n",
    "rating_pattern = re.compile(r'<span class=\"rating_num\" property=\"v:average\">([\\d.]+)</span>')\n",
    "ratings = rating_pattern.findall(html_content)\n",
    "```\n",
    "\n",
    "#### **解释：**\n",
    "- **正则表达式**：`<span class=\"rating_num\" property=\"v:average\">([\\d.]+)</span>`\n",
    "- **匹配内容**：电影评分，如 `<span class=\"rating_num\" property=\"v:average\">8.9</span>`\n",
    "\n",
    "**具体解释：**\n",
    "- `<span class=\"rating_num\" property=\"v:average\">`：这部分用于精确定位包含电影评分的 `span` 标签，`class` 为 `rating_num`，并且 `property` 属性为 `v:average`。这些标签都表明这部分内容是评分。\n",
    "- `([\\d.]+)`：这是一个捕获组，`[\\d.]` 表示数字 `0-9` 或 `.`（小数点），`+` 表示 **匹配 1 次或多次**。因此它可以提取评分数据（包括整数和小数部分）。\n",
    "- `</span>`：关闭 `span` 标签。\n",
    "\n",
    "**工作原理**：该表达式会从评分的 HTML 片段中提取数字部分。`[\\d.]+` 可以匹配评分的数值部分，确保能够抓取整数和小数的评分（如 8.7、9.1 等）。\n",
    "\n",
    "---\n",
    "\n",
    "### **3. 匹配导演信息**\n",
    "\n",
    "```python\n",
    "director_pattern = re.compile(r'导演: ([^<]+)')\n",
    "directors = director_pattern.findall(html_content)\n",
    "```\n",
    "\n",
    "#### **解释：**\n",
    "- **正则表达式**：`导演: ([^<]+)`\n",
    "- **匹配内容**：导演的名字，如 `导演: 张艺谋`\n",
    "\n",
    "**具体解释：**\n",
    "- `导演: `：表示导演信息在网页中的固定部分，帮助我们定位到含有导演名字的地方。\n",
    "- `([^<]+)`：捕获组，表示匹配除 `<` 以外的任意字符，`+` 表示匹配 1 次或多次。这意味着我们会提取 `导演: ` 后面的一段文字，直到遇到 `<` 标签为止。这部分正好对应了导演的名字。\n",
    "\n",
    "**工作原理**：该表达式从 HTML 结构中找到包含 \"导演\" 字样的文本，提取名字部分。`[^<]+` 确保我们只抓取导演名字，而不会包括 HTML 标签。\n",
    "\n",
    "---\n",
    "\n",
    "### **4. 匹配简短电影描述**\n",
    "\n",
    "```python\n",
    "quote_pattern = re.compile(r'<span class=\"inq\">([^<]+)</span>')\n",
    "quotes = quote_pattern.findall(html_content)\n",
    "```\n",
    "\n",
    "#### **解释：**\n",
    "- **正则表达式**：`<span class=\"inq\">([^<]+)</span>`\n",
    "- **匹配内容**：简短描述，如 `<span class=\"inq\">这是一个简短的描述。</span>`\n",
    "\n",
    "**具体解释：**\n",
    "- `<span class=\"inq\">`：表示 `span` 标签的起始部分，`class` 为 `inq`。这通常是豆瓣电影中显示简短评论的地方。\n",
    "- `([^<]+)`：捕获组，匹配除了 `<` 以外的任意字符，`+` 表示 1 次或多次。用于提取评论文本。\n",
    "- `</span>`：关闭 `span` 标签。\n",
    "\n",
    "**工作原理**：该表达式从网页中提取简短的电影描述。通过 `([^<]+)` 来确保提取 `span` 标签内的内容，而不是其他 HTML 结构。\n",
    "\n",
    "---\n",
    "\n",
    "### 正则表达式的选择原因\n",
    "\n",
    "- **结构化 HTML**：豆瓣电影页面使用非常规则的 HTML 标签，因此我们可以通过匹配固定的标签来提取信息。这些标签中包含的内容（如标题、评分、导演等）都可以通过正则表达式来精确匹配。\n",
    "  \n",
    "- **避免匹配不必要的内容**：通过使用 `([^<]+)` 来提取内容，确保匹配的只是我们需要的信息（如电影名称、评分、导演等），而不是 HTML 标签或其他非文本内容。\n",
    "\n",
    "---\n",
    "\n",
    "### 总结：\n",
    "\n",
    "通过上述正则表达式，我们可以从网页的 HTML 结构中提取出有用的关键信息，如电影标题、评分、导演和简评。使用捕获组 `()` 提取特定的内容，结合 `[^<]` 来避免 HTML 标签的干扰是这些正则表达式设计的核心。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "2d938ca5-70e0-4aa1-b376-5fc6e8df3ada",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.12.3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
